package com.tianlang.web.weixin.controller;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.Logger;

import com.jfinal.kit.PropKit;
import com.jfinal.weixin.sdk.api.ApiResult;
import com.jfinal.weixin.sdk.api.SnsAccessTokenApi;
import com.jfinal.weixin.sdk.api.TemplateData;
import com.jfinal.weixin.sdk.api.TemplateMsgApi;
import com.jfinal.weixin.sdk.jfinal.MsgControllerAdapter;
import com.jfinal.weixin.sdk.msg.in.InImageMsg;
import com.jfinal.weixin.sdk.msg.in.InLinkMsg;
import com.jfinal.weixin.sdk.msg.in.InLocationMsg;
import com.jfinal.weixin.sdk.msg.in.InTextMsg;
import com.jfinal.weixin.sdk.msg.in.InVideoMsg;
import com.jfinal.weixin.sdk.msg.in.InVoiceMsg;
import com.jfinal.weixin.sdk.msg.in.event.InCustomEvent;
import com.jfinal.weixin.sdk.msg.in.event.InFollowEvent;
import com.jfinal.weixin.sdk.msg.in.event.InLocationEvent;
import com.jfinal.weixin.sdk.msg.in.event.InMassEvent;
import com.jfinal.weixin.sdk.msg.in.event.InMenuEvent;
import com.jfinal.weixin.sdk.msg.in.event.InQrCodeEvent;
import com.jfinal.weixin.sdk.msg.in.event.InTemplateMsgEvent;
import com.jfinal.weixin.sdk.msg.in.speech_recognition.InSpeechRecognitionResults;
import com.jfinal.weixin.sdk.msg.out.OutImageMsg;
import com.jfinal.weixin.sdk.msg.out.OutMusicMsg;
import com.jfinal.weixin.sdk.msg.out.OutNewsMsg;
import com.jfinal.weixin.sdk.msg.out.OutTextMsg;
import com.jfinal.weixin.sdk.msg.out.OutVoiceMsg;
import com.tianlang.annotation.ControllerBind;
import com.tianlang.util.BaiduTranslate;
import com.tianlang.util.FaceUtils;
import com.tianlang.util.WeiXinUtils;

/**
 * 将此 DemoController 在YourJFinalConfig 中注册路由，
 * 并设置好weixin开发者中心的 URL 与 token ，使 URL 指向该
 * DemoController 继承自父类 WeixinController 的 index
 * 方法即可直接运行看效果，在此基础之上修改相关的方法即可进行实际项目开发
 * @author mcp
 *
 */
@ControllerBind(controllerKey = "/WeixinMsg")
public class WeixinMsgController extends MsgControllerAdapter {

	private static Logger log = Logger.getLogger(WeixinMsgController.class);

	/**
	 * 关注/取消关注消息
	 */
	@Override
	protected void processInFollowEvent(InFollowEvent inFollowEvent) {
		// 事件
		String event = inFollowEvent.getEvent();
		String fromUserName = inFollowEvent.getFromUserName();
		String toUserName = inFollowEvent.getToUserName();
		String msgType = inFollowEvent.getMsgType();
		Integer createTime = inFollowEvent.getCreateTime();
		log.info("event:" + event + " fromUserName:" + fromUserName + " toUserName:" + toUserName + " msgType:"
				+ msgType + " createTime:" + createTime);
		if (InFollowEvent.EVENT_INFOLLOW_SUBSCRIBE.equals(inFollowEvent.getEvent())) {
			OutTextMsg outMsg = new OutTextMsg(inFollowEvent);
			outMsg.setContent("微信公众号开发测试:关注");
			render(outMsg);
		}
		// 如果为取消关注事件，将无法接收到传回的信息
		if (InFollowEvent.EVENT_INFOLLOW_UNSUBSCRIBE.equals(inFollowEvent.getEvent())) {
			log.info("取消关注：" + fromUserName);
		}
	}

	/**
	 * 实现父类抽方法，处理文本消息
	 * 本例子中根据消息中的不同文本内容分别做出了不同的响应，同时也是为了测试 jfinal weixin sdk的基本功能：
	 * 本方法仅测试了 OutTextMsg、OutNewsMsg、OutMusicMsg 三种类型的OutMsg，
	 * 其它类型的消息会在随后的方法中进行测试
	 */
	@Override
	protected void processInTextMsg(InTextMsg inTextMsg) {
		String msgContent = inTextMsg.getContent().trim();
		String helpStr = "帮助、人脸识别、翻译、新闻、音乐、美女、授权、模板消息...";
		if (msgContent.startsWith("帮助")) {
			// 帮助提示
			renderOutTextMsg(helpStr);
		} else if (msgContent.startsWith("人脸")) {
			msgContent = "请发一张清晰的照片！" + WeiXinUtils.emoji(0x1F4F7);
			renderOutTextMsg(msgContent);
		} else if (msgContent.startsWith("翻译")) {
			try {
				msgContent = BaiduTranslate.Translates(msgContent);
			} catch (Exception e) {
				msgContent = "\ue252 翻译出错了 \n\n" + BaiduTranslate.getGuide();
			}
			renderOutTextMsg(msgContent);
		} else if (msgContent.startsWith("新闻")) {
			// 图文消息测试
			OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
			outMsg.addNews("JFinal 2.0 发布,JAVA 极速 WEB+ORM 框架", "本星球第一个极速开发框架",
					"https://mmbiz.qlogo.cn/mmbiz/KJoUl0sqZFS0fRW68poHoU3v9ulTWV8MgKIduxmzHiamkb3yHia8pCicWVMCaFRuGGMnVOPrrj2qM13u9oTahfQ9A/0?wx_fmt=png",
					"http://mp.weixin.qq.com/s?__biz=MzA4NjM4Mjk2Mw==&mid=211063163&idx=1&sn=87d54e2992237a3f791f08b5cdab7990#rd");
			outMsg.addNews("JFinal 1.8 发布,JAVA 极速 WEB+ORM 框架", "现在就加入 JFinal极速开发世界，节省更多时间去跟女友游山玩水 ^_^",
					"http://mmbiz.qpic.cn/mmbiz/zz3Q6WSrzq1ibBkhSA1BibMuMxLuHIvUfiaGsK7CC4kIzeh178IYSHbYQ5eg9tVxgEcbegAu22Qhwgl5IhZFWWXUw/0",
					"http://mp.weixin.qq.com/s?__biz=MjM5ODAwOTU3Mg==&mid=200313981&idx=1&sn=3bc5547ba4beae12a3e8762ababc8175#rd");
			outMsg.addNews("JFinal 1.6 发布,JAVA 极速 WEB+ORM 框架", "JFinal 1.6 主要升级了ActiveRecord 插件，本次升级全面支持多数源、多方言、多缓",
					"http://mmbiz.qpic.cn/mmbiz/zz3Q6WSrzq0fcR8VmNCgugHXv7gVlxI6w95RBlKLdKUTjhOZIHGSWsGvjvHqnBnjIWHsicfcXmXlwOWE6sb39kA/0",
					"http://mp.weixin.qq.com/s?__biz=MjM5ODAwOTU3Mg==&mid=200121522&idx=1&sn=ee24f352e299b2859673b26ffa4a81f6#rd");
			render(outMsg);
		} else if (msgContent.startsWith("音乐")) {
			// 音乐消息测试
			OutMusicMsg outMsg = new OutMusicMsg(inTextMsg);
			outMsg.setTitle("When The Stars Go Blue-Venke Knutson");
			outMsg.setDescription("建议在 WIFI 环境下流畅欣赏此音乐");
			outMsg.setMusicUrl("http://www.jfinal.com/When_The_Stars_Go_Blue-Venke_Knutson.mp3");
			outMsg.setHqMusicUrl("http://www.jfinal.com/When_The_Stars_Go_Blue-Venke_Knutson.mp3");
			outMsg.setFuncFlag(true);
			render(outMsg);
		} else if (msgContent.startsWith("美女")) {
			OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
			outMsg.addNews("JFinal 宝贝更新喽", "jfinal 宝贝更新喽，我们只看美女 ^_^",
					"https://mmbiz.qlogo.cn/mmbiz/KJoUl0sqZFRHa3VrmibqAXRfYPNdiamFnpPTOvXoxsFlRoOHbVibGhmHOEUQiboD3qXWszKuzWpibFxsVW1RmNB9hPw/0?wx_fmt=jpeg",
					"http://mp.weixin.qq.com/s?__biz=MzA4NjM4Mjk2Mw==&mid=211356950&idx=1&sn=6315a1a2848aa8cb0694bf1f4accfb07#rd");
			outMsg.addNews("秀色可餐", "JFinal Weixin 极速开发就是这么爽，有木有 ^_^",
					"http://mmbiz.qpic.cn/mmbiz/zz3Q6WSrzq2GJLC60ECD7rE7n1cvKWRNFvOyib4KGdic3N5APUWf4ia3LLPxJrtyIYRx93aPNkDtib3ADvdaBXmZJg/0",
					"http://mp.weixin.qq.com/s?__biz=MjM5ODAwOTU3Mg==&mid=200987822&idx=1&sn=7eb2918275fb0fa7b520768854fb7b80#rd");
			render(outMsg);
		} else if (msgContent.startsWith("授权")) {
			String calbackUrl = "http://demo.bianguo.com.cn/hupeng/html5/room/index.php/Portal/emoty/index/";
			String url = SnsAccessTokenApi.getAuthorizeURL(PropKit.get("appId"), calbackUrl, "111", false);
			String urlStr = "<a href=\"" + url + "\">点击我授权</a>";
			renderOutTextMsg("授权地址" + urlStr);
		} else if (msgContent.startsWith("模板")) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日  HH:mm:ss");
			String time = sdf.format(new Date());
			String json = TemplateData.New().setTouser(inTextMsg.getFromUserName())
					.setTemplate_id("jias1ZXs2dmsGiewKX8tXkydr8UsyniPVfckiaCcqb8").setUrl("http://www.baidu.com")
					.add("user", inTextMsg.getFromUserName(), "#0000FF").add("time", time, "#0000FF").build();
			System.out.println(json);
			ApiResult result = TemplateMsgApi.send(json);
			renderNull();
		} else {
			// 其它文本消息直接返回原值 + 帮助提示
			renderOutTextMsg("\t文本消息已成功接收，内容为： " + inTextMsg.getContent() + "\n\n" + helpStr);
		}
	}

	/**
	 * 处理图片消息
	 */
	@Override
	protected void processInImageMsg(InImageMsg inImageMsg) {
		String picUrl = inImageMsg.getPicUrl();
		String respContent = FaceUtils.detect(picUrl);
		if (respContent.startsWith("未识别到人脸")) {
			OutImageMsg outMsg = new OutImageMsg(inImageMsg);
			// 将刚发过来的图片再发回去
			outMsg.setMediaId(inImageMsg.getMediaId());
			render(outMsg);
			return;
		}
		renderOutTextMsg(respContent);
	}

	/**
	* 处理语音消息
	*/
	@Override
	protected void processInVoiceMsg(InVoiceMsg inVoiceMsg) {
		OutVoiceMsg outMsg = new OutVoiceMsg(inVoiceMsg);
		// 将刚发过来的语音再发回去
		outMsg.setMediaId(inVoiceMsg.getMediaId());
		render(outMsg);
	}

	/**
	 * 处理视频消息
	 */
	@Override
	protected void processInVideoMsg(InVideoMsg inVideoMsg) {
		// 腾讯 api 有 bug，无法回复视频消息，暂时回复文本消息代码测试
		/*
		 * OutVideoMsg outMsg = new OutVideoMsg(inVideoMsg); outMsg.setTitle(
		 * "OutVideoMsg 发送"); outMsg.setDescription("刚刚发来的视频再发回去");
		 * outMsg.setMediaId(inVideoMsg.getMediaId()); render(outMsg);
		 */
		OutTextMsg outMsg = new OutTextMsg(inVideoMsg);
		outMsg.setContent("\t视频消息已成功接收，该视频的 mediaId 为: " + inVideoMsg.getMediaId());
		render(outMsg);
	}

	/**
	 * 处理小视频消息
	 */
	/*
	 * @Override protected void processInShortVideoMsg(InShortVideoMsg
	 * inShortVideoMsg) { OutTextMsg outMsg = new OutTextMsg(inShortVideoMsg);
	 * outMsg.setContent("\t视频消息已成功接收，该视频的 mediaId 为: " +
	 * inShortVideoMsg.getMediaId()); render(outMsg); }
	 */

	/**
	* 处理地址位置消息
	*/
	@Override
	protected void processInLocationMsg(InLocationMsg inLocationMsg) {
		OutTextMsg outMsg = new OutTextMsg(inLocationMsg);
		outMsg.setContent("已收到地理位置消息:" + "\nlocation_X = " + inLocationMsg.getLocation_X() + "\nlocation_Y = "
				+ inLocationMsg.getLocation_Y() + "\nscale = " + inLocationMsg.getScale() + "\nlabel = "
				+ inLocationMsg.getLabel());
		render(outMsg);
	}

	/**
	* 处理链接消息
	* 特别注意：测试时需要发送我的收藏中的曾经收藏过的图文消息，直接发送链接地址会当做文本消息来发送
	*/
	@Override
	protected void processInLinkMsg(InLinkMsg inLinkMsg) {
		OutNewsMsg outMsg = new OutNewsMsg(inLinkMsg);
		outMsg.addNews("链接消息已成功接收", "", "http://image.tianjimedia.com/uploadImages/2014/289/01/IGS09651F94M.jpg",
				inLinkMsg.getUrl());
		render(outMsg);
	}

	/**
	 * 处理接收到的多客服管理事件
	 */
	@Override
	protected void processInCustomEvent(InCustomEvent inCustomEvent) {
		log.info("测试方法：processInCustomEvent()");
		renderNull();
	}

	/***********************************************************/

	/*
	 * @Override protected void processInLocationMsg(InLocationMsg
	 * inLocationMsg) { // 转发给多客服PC客户端 OutCustomMsg outCustomMsg = new
	 * OutCustomMsg(inLocationMsg); render(outCustomMsg); }
	 */

	/*
	 * @Override protected void processInLinkMsg(InLinkMsg inLinkMsg) { //
	 * 转发给多客服PC客户端 OutCustomMsg outCustomMsg = new OutCustomMsg(inLinkMsg);
	 * render(outCustomMsg); }
	 */

	@Override
	protected void processInQrCodeEvent(InQrCodeEvent inQrCodeEvent) {
		if (InQrCodeEvent.EVENT_INQRCODE_SUBSCRIBE.equals(inQrCodeEvent.getEvent())) {
			log.debug("扫码未关注：" + inQrCodeEvent.getFromUserName());
			OutTextMsg outMsg = new OutTextMsg(inQrCodeEvent);
			outMsg.setContent("感谢您的关注，二维码内容：" + inQrCodeEvent.getEventKey());
			render(outMsg);
		}
		if (InQrCodeEvent.EVENT_INQRCODE_SCAN.equals(inQrCodeEvent.getEvent())) {
			log.debug("扫码已关注：" + inQrCodeEvent.getFromUserName());
		}
	}

	@Override
	protected void processInLocationEvent(InLocationEvent inLocationEvent) {
		log.debug("发送地理位置事件：" + inLocationEvent.getFromUserName());
		OutTextMsg outMsg = new OutTextMsg(inLocationEvent);
		outMsg.setContent("地理位置是：" + inLocationEvent.getLatitude());
		render(outMsg);
	}

	@Override
	protected void processInMassEvent(InMassEvent inMassEvent) {
		log.debug("测试方法：processInMassEvent()");
		renderNull();
	}

	/**
	 * 实现父类抽方法，处理自定义菜单事件
	 */
	@Override
	protected void processInMenuEvent(InMenuEvent inMenuEvent) {
		log.debug("菜单事件：" + inMenuEvent.getFromUserName());
		OutTextMsg outMsg = new OutTextMsg(inMenuEvent);
		outMsg.setContent("菜单事件内容是：" + inMenuEvent.getEventKey());
		render(outMsg);
	}

	@Override
	protected void processInSpeechRecognitionResults(InSpeechRecognitionResults inSpeechRecognitionResults) {
		log.debug("语音识别事件：" + inSpeechRecognitionResults.getFromUserName());
		OutTextMsg outMsg = new OutTextMsg(inSpeechRecognitionResults);
		outMsg.setContent("语音识别内容是：" + inSpeechRecognitionResults.getRecognition());
		render(outMsg);
	}

	@Override
	protected void processInTemplateMsgEvent(InTemplateMsgEvent inTemplateMsgEvent) {
		log.debug("测试方法：processInTemplateMsgEvent()");
		renderNull();
	}

	//
	// /**
	// * 实现父类抽方法，处理扫描带参数二维码事件
	// */
	// protected void processInQrCodeEvent(InQrCodeEvent inQrCodeEvent) {
	// OutTextMsg outMsg = new OutTextMsg(inQrCodeEvent);
	// outMsg.setContent("processInQrCodeEvent() 方法测试成功");
	// render(outMsg);
	// }
	//
	// /**
	// * 实现父类抽方法，处理上报地理位置事件
	// */
	// protected void processInLocationEvent(InLocationEvent inLocationEvent) {
	// OutTextMsg outMsg = new OutTextMsg(inLocationEvent);
	// outMsg.setContent("processInLocationEvent() 方法测试成功");
	// render(outMsg);
	// }
	//
	// @Override
	// protected void processInMassEvent(InMassEvent inMassEvent)
	// {
	// System.out.println("processInMassEvent() 方法测试成功");
	// }
	//
	// /**
	// * 实现父类抽方法，处理自定义菜单事件
	// */
	// protected void processInMenuEvent(InMenuEvent inMenuEvent) {
	// renderOutTextMsg("processInMenuEvent() 方法测试成功");
	// }
	//
	// /**
	// * 实现父类抽方法，处理接收语音识别结果
	// */
	// protected void
	// processInSpeechRecognitionResults(InSpeechRecognitionResults
	// inSpeechRecognitionResults) {
	// renderOutTextMsg("语音识别结果： " +
	// inSpeechRecognitionResults.getRecognition());
	// }
	//
	// // 处理接收到的模板消息是否送达成功通知事件
	// protected void processInTemplateMsgEvent(InTemplateMsgEvent
	// inTemplateMsgEvent) {
	// String status = inTemplateMsgEvent.getStatus();
	// renderOutTextMsg("模板消息是否接收成功：" + status);
	// }
	// @Override
	// protected void
	// processInShakearoundUserShakeEvent(InShakearoundUserShakeEvent
	// inShakearoundUserShakeEvent) {
	// log.debug("摇一摇周边设备信息通知事件：" +
	// inShakearoundUserShakeEvent.getFromUserName());
	// OutTextMsg outMsg = new OutTextMsg(inShakearoundUserShakeEvent);
	// outMsg.setContent("摇一摇周边设备信息通知事件UUID：" +
	// inShakearoundUserShakeEvent.getUuid());
	// render(outMsg);
	// }
	//
	// @Override
	// protected void processInVerifySuccessEvent(InVerifySuccessEvent
	// inVerifySuccessEvent) {
	// log.debug("资质认证成功通知事件：" + inVerifySuccessEvent.getFromUserName());
	// OutTextMsg outMsg = new OutTextMsg(inVerifySuccessEvent);
	// outMsg.setContent("资质认证成功通知事件：" + inVerifySuccessEvent.getExpiredTime());
	// render(outMsg);
	// }
	//
	// @Override
	// protected void processInVerifyFailEvent(InVerifyFailEvent
	// inVerifyFailEvent){
	// log.debug("资质认证失败通知事件：" + inVerifyFailEvent.getFromUserName());
	// OutTextMsg outMsg = new OutTextMsg(inVerifyFailEvent);
	// outMsg.setContent("资质认证失败通知事件：" + inVerifyFailEvent.getFailReason());
	// render(outMsg);
	// }
	//
	// /**
	// * 处理微信硬件绑定和解绑事件
	// * @param InEqubindEvent 处理微信硬件绑定和解绑事件
	// */
	// @Override
	// protected void processInEqubindEvent(InEqubindEvent msg) {
	// String deviceType = msg.getDeviceType();
	// String deviceID = msg.getDeviceID();
	// String openID = msg.getOpenID();
	// String event = msg.getEvent();
	// String sessionID= msg.getSessionID();
	//
	// System.out.printf("收到消息,Openid,DeviceId,event:%s;%s;%s",msg.getOpenID(),msg.getDeviceID(),msg.getEvent());
	// System.out.println(":DeviceType:" + deviceType);
	// System.out.println(":sessionID:" + sessionID);
	//
	// // 存储用户和设备的绑定关系
	// // 设备绑定/解绑事件可以回复空包体
	// if(InEqubindEvent.BIND.equals(event)){
	// // DO 业务
	// }else{
	// // DO 业务
	// }
	// //respons event
	// OutEquDataMsg oeqmsg = new OutEquDataMsg(msg);
	// oeqmsg.setContent("");
	// oeqmsg.setDeviceID(deviceID);
	// oeqmsg.setDeviceType(deviceType);
	// oeqmsg.setSessionID(sessionID);
	// render(oeqmsg);
	// }
	//
	// /**
	// * 处理微信硬件发来数据
	// * @param InEquDataMsg 处理微信硬件发来数据
	// */
	// @Override
	// protected void processInEquDataMsg(InEquDataMsg msg) {
	// String reqContent = msg.getContent();
	// // Base64解码
	// byte[] reqRaw = Base64Utils.decodeBase64(reqContent);
	// // 反序列化
	// BlueLight lightReq = BlueLight.parse(reqRaw);
	//
	// // 逻辑处理
	// // demo中 推送消息给用户微信
	// String reqText = lightReq.body;
	// System.out.println("recv text:" + reqText);
	// String transText = "收到设备发送的数据：";
	//
	// byte[] reqTextRaw = reqText.getBytes(Charsets.UTF_8);
	//
	// if (reqTextRaw.length > 0 && reqTextRaw[reqTextRaw.length - 1] == 0) {
	// // 推送给微信用户的内容去掉末尾的反斜杠零'\0'
	// transText = transText + new String(reqTextRaw, 0, reqTextRaw.length - 1,
	// Charsets.UTF_8);
	// } else{
	// transText = transText + reqText;
	// }
	//
	// // 推送文本消息给微信
	// //MpApi.customSendText(openID, transText);
	//
	// // demo中 回复 收到的内容给设备
	// BlueLight lightResp = BlueLight.build(BlueLight.CmdId.SEND_TEXT_RESP,
	// reqText, lightReq.head.seq);
	// // 序列化
	// byte[] respRaw = lightResp.toBytes();
	// // Base64编码
	// String respCon = Base64Utils.encode(respRaw);
	// System.out.println(respCon);
	// // 设备消息接口必须回复符合协议的xml
	// //TODO 解析并获取测量值
	// renderOutTextMsg(transText);
	// }
}
